#ifndef ARCH_MEMORY_H
#define ARCH_MEMORY_H

#include <lib/type.h>

#define	tlb_flush_one(addr)	\
	__asm__ __volatile__	("invlpg	(%0)	\n\t"::"r"(addr):"memory")

#define tlb_flush()						\
do								\
{								\
	unsigned long	tmpreg;					\
	__asm__ __volatile__ 	(				\
				"movl	%%cr3,	%0	\n\t"	\
				"movl	%0,	%%cr3	\n\t"	\
				:"=r"(tmpreg)			\
				:				\
				:"memory"			\
				);				\
}while(0)

/* x86特性 */
#define X86_FEATURE_XMM2 (0 * 32 + 26) /* Streaming SIMD Extensions-2 */

/*
* Alternative instructions for different CPU types or capabilities.
*
* This allows to use optimized instructions even on generic binary
* kernels.
*
* length of oldinstr must be longer or equal the length of newinstr
* It can be padded with nops as needed.
*
* For non barrier like inlines please define new variants
* without volatile and memory clobber.
*/
#define alternative(oldinstr, newinstr, feature)                  \
    asm volatile("661:\n\t" oldinstr "\n662:\n"                   \
                 ".section .altinstructions,\"a\"\n"              \
                 "   .align 4\n"                                  \
                 "   .long 661b\n"      /* label */               \
                 "   .long 663f\n"      /* new instruction */     \
                 "   .byte %c0\n"       /* feature bit */         \
                 "   .byte 662b-661b\n" /* sourcelen */           \
                 "   .byte 664f-663f\n" /* replacementlen */      \
                 ".previous\n"                                    \
                 ".section .altinstr_replacement,\"ax\"\n"        \
                 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
                 ".previous" ::"i"(feature)                       \
                 : "memory")

#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)

#ifdef CONFIG_X86_OOSTORE
/* Actually there are no OOO store capable CPUs for now that do SSE, 
but make it already an possibility. */
#define wmb() Alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
#else
#define wmb() __asm__ __volatile__("" \
                                   :  \
                                   :  \
                                   : "memory")
#endif

/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("" \
                                       :  \
                                       :  \
                                       : "memory")


uint32_t BackTrace(void **buffer, uint32_t size);
#endif